from abc import ABC
from Alibb.handlers import BaseHandler
from apps.token.form import GetCodeForm
from datetime import datetime
from time import time

from ujson import loads
from jwt import encode as jwt_encode


class GetCodeHandler(BaseHandler, ABC):

    @staticmethod
    def join_sql(text):

        sql = f"""
INSERT INTO alibb.`alibb_market_user` (
  member_id,
  access_token,
  ali_id,
  refresh_token,
  resource_owner,
  expires_in,
  refresh_token_timeout,
  add_time
)
VALUES
  (
    "{text['memberId']}",
    "{text['access_token']}",
    "{text['aliId']}",
    "{text['refresh_token']}",
    "{text['resource_owner']}",
    "{text['expires_in']}",
    "{text['refresh_token_timeout']}",
    now()
  )
  ON DUPLICATE KEY
  UPDATE
    access_token = "{text['access_token']}",
    expires_in = "{text['expires_in']}"
"""
        return sql

    def get_jwt(self, text_):

        payload = {
            'id': text_['memberId'],
            'exp': datetime.utcnow()  # 必须要用utc
        }

        token = jwt_encode(payload, self.application.settings['secret_key'], algorithm='HS256')

        return token.decode('utf8')

    async def req_auth(self, code_):
        url = 'https://gw.open.1688.com/openapi/http/1/system.oauth2/getToken/' + self.application.settings["app_key"]

        params = {
            'grant_type': 'authorization_code',
            'need_refresh_token': 'true',
            'client_id': self.application.settings["app_key"],
            'client_secret': self.application.settings["app_secret"],
            'redirect_uri': "http://albeibei.cn:8887/alibb/oo/v1/get/code",
            'code': code_
        }

        async with self.application.session.post(url, params=params, timeout=5) as resp:
            status_code = resp.status
            text = await resp.text()

        return status_code, loads(text)

    async def get(self):

        code = self.get_argument('code')

        form = GetCodeForm.from_json({"code": code})

        if not form.validate():
            for error in form.errors:
                self.set_status(403)
                return await self.finish({"error": form.errors[error][0]})

        # 获取token
        status_code, text = await self.req_auth(form.code.data)

        if status_code != 200:
            self.set_status(403)
            return await self.finish({"error": text['error_description']})

        # 拼接sql
        sql = self.join_sql(text)

        # 将数据写入到数据库
        try:
            await self.insert(sql, "授权信息写入数据库失败", sql)
        except Exception:
            self.set_status(403)
            return await self.finish({"error": "授权信息写入数据库失败"})

        # 生成JWT, 设置cookies有效期10小时
        self.set_cookie("JSESSION", self.get_jwt(text), expires=time() + 36000)

        await self.finish({"msg": "授权成功"})
